import {warn} from "../../shared/warn";
import {emptyNode, HTML_NODE_TYPE, HTML_TAG_STATUS} from "../../constant";
import {isReservedTag} from "../../platform/util";
import ASTNode from "../../type/ASTNode";
import {ASTParser} from "./ASTParser";
import {isDef} from "../../shared/util";

/**
 * 分析 AST 节点上的 v-pre 指令
 * @param {ASTNode} astNode
 */
export function processPre (astNode) {
    // 处理未被 v-pre 语法标记，但在 v-pre 作用域下的节点
    // 如果在 v-pre 作用域内，直接跳过处理
    if (ASTParser.inPre) {
        // 节点被标记为 静态节点
        astNode.isDynamic = false;
    }
    // 如果该节点 pre 被标记
    if (astNode.conditionBitMap.pre) {
        // 在 v-pre 作用域范围内，提示用户
        if (ASTParser.inPre) {
            // 取消 v-pre 语法标记
            astNode.conditionBitMap.pre = false;
            // 提示用户信息
            const message = `请不要在 v-pre 作用域下再次声明 v-pre`;
            warn(message);
        }
        // 不在 v-pre 作用域下，进行 v-pre 的处理
        if (!astNode.elementProcessed && astNode.conditionBitMap.pre) {
            // 设置 ASTParser.inPre 全局标志
            ASTParser.preStateStack.push(ASTParser.inPre);
            ASTParser.inPre = true;
            // 设置 conditionMessage
            astNode.conditionMessage.pre = {pre: true};
            // 节点被标记为 静态节点
            astNode.isDynamic = false;
        }
    }
}

// for 循环迭代变量 正则表达式
const FOR_EXP_REGEX = /([\s\S]*)\s+(in|of)\s+([\s\S]*)/;
// 匹配 for 表达式的迭代变量
const FOR_EXP_ITERATOR_REGEX = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
// 匹配开始括号 或 结束括号
const stripParensRE = /^\(|\)$/g

/**
 * 将 v-for 指令的值传入，分析指令的分析结果
 * @param {String} forValueStr
 */
function parseForExpression (forValueStr) {
    // for 的解析结果
    const forMessage = {
        iter1: undefined,
        iter2: undefined,
        alias: undefined,
        index: false,
        opt: undefined,
        obj: null,
        number: 0
    };

    // 解析 v-for 指令信息
    const matchResult = FOR_EXP_REGEX.exec(forValueStr);
    if ( !matchResult ) return;
    // 获取 for 操作符
    forMessage.opt = matchResult[2];
    // 获取 迭代变量
    const iteratorValueStr = matchResult[1].trim().replace(stripParensRE, '').trim();
    const iteratorResult = FOR_EXP_ITERATOR_REGEX.exec(iteratorValueStr);
    if ( !iteratorResult ) {
        // 迭代变量
        forMessage.iter1 = iteratorValueStr;
        forMessage.iter2 = undefined;
        // 赋予别名
        forMessage.alias = forMessage.iter1;
        // 迭代变量数量
        forMessage.number = 1;
    }
    else {
        // 迭代变量
        forMessage.iter1 = iteratorValueStr.substring(0, iteratorResult.index);
        forMessage.iter2 = iteratorResult[1].trim();
        // 赋予别名
        forMessage.alias = forMessage.iter1;
        forMessage.index = forMessage.iter2;

        // fixme 这部分发生了修改， 最后一个是 index
        // forMessage.iter1 === "index"
        //     ? forMessage.index = true
        //     : forMessage.alias = forMessage.iter1;
        // forMessage.iter2 === "index"
        //     ? forMessage.index = true
        //     : forMessage.alias = forMessage.iter2;

        // 迭代变量数量
        forMessage.number = 2;
    }
    // 获取 被迭代对象
    forMessage.obj = matchResult[3].trim();

    // 返回 分析结果
    return forMessage;
}

/**
 * 处理 AST 节点上的 v-for 指令
 * @param {ASTNode} astNode
 */
export function processFor (astNode) {

    // 如果该节点仍需要被处理
    if (!astNode.elementProcessed) {
        // 该节点被 v-for 语法指令标记
        if (astNode.conditionBitMap.for) {
            // 不允许在 v-pre 作用域下，使用 v-for 指令
            if (ASTParser.inPre) {
                // 取消 v-for 指令标记
                astNode.conditionBitMap.for = false;
                // 提示用户信息
                const message = `请不要在 v-pre 作用域下，使用 v-for 指令`;
                warn(message);
            }
            // 处理 v- for 语法指令标记
            if (astNode.conditionBitMap.for) {
                // ASTParser.inFor 全局标志 入栈
                ASTParser.forStateStack.push(ASTParser.inFor);
                // v-for 全局标志 置位
                ASTParser.inFor = true;
                // 处理 v-for 的指令信息
                let forValueStr = astNode.conditionStrValueMap.for;
                const forParseResult = parseForExpression(forValueStr);
                // 将 v-for 的分析结果储存在 conditionMessage 中
                astNode.conditionMessage.for = forParseResult;
            }
        }
    }

}

/**
 * 处理 AST 节点上的 v-key 指令
 * @param {ASTNode} astNode
 */
export function processKey (astNode) {
    // 如果该节点仍需要被处理
    if (!astNode.elementProcessed) {
        // 该节点被 v-key 语法指令标记
        if (astNode.conditionBitMap.key) {
            // 不允许在 v-pre 作用域下，使用 v-key 指令
            if (ASTParser.inPre) {
                // 取消 v-for 指令标记
                astNode.conditionBitMap.key = false;
                // 提示用户信息
                const message = `请不要在 v-pre 作用域下，使用 v-key 指令`;
                warn(message);
            }
            if (astNode.tag === 'template') {
                // 取消 v-for 指令标记
                astNode.conditionBitMap.key = false;
                // 提示用户信息
                const message = `v-key 不能被标记在 template 标签上，请标记在一个实际渲染的标签上`;
                warn(message);
            }
            // 处理 v-key 语法指令标记
            if (astNode.conditionBitMap.key) {
                // 处理 v-key 的指令信息
                let keyValueStr = astNode.conditionStrValueMap.key;
                // 记录 show 指令信息
                astNode.conditionMessage.key = {
                    exp: keyValueStr
                };
            }
        }
    }
}

/**
 * 分析 AST 节点上的 v-if 指令
 * @param {ASTNode} astNode
 */
export function processIf (astNode) {

    // 节点仍需被处理指令
    if (!astNode.elementProcessed) {
        // 语法被 v-if ,v-else-if , v-else 标记
        if (astNode.conditionBitMap.if
            || astNode.conditionBitMap.elseIf
            || astNode.conditionBitMap.else) {
            // 不允许在 v-pre 作用域内，使用 v-if， v-else-if， v-else 语法指令
            if (ASTParser.inPre) {
                // 取消该节点上的 once 指令标记
                astNode.conditionBitMap.if = false;
                // 后面两句应该是不需要的
                astNode.conditionBitMap.elseIf = false;
                astNode.conditionBitMap.else = false;
                // 发出警告
                const message = `${astNode.tag} 在v-pre范围，请不要使用任何动态指令.`;
                warn(message);
            }
            // 处理 if 语句
            if (astNode.conditionBitMap.if) {
                const expression = astNode.conditionStrValueMap.if;
                // 设置 if 指令信息
                astNode.conditionMessage.if === undefined ?
                    astNode.conditionMessage.if = new Array()
                    : undefined;
                astNode.conditionMessage.if.push({
                    exp: expression,
                    block: astNode
                });
            }
            // 处理 elseIf 语句
            if (astNode.conditionBitMap.elseIf) {
                // 不允许在同一个节点使用 v-if， v-else-if， v-else 语法指令
                if (astNode.conditionMessage.if) {
                    // 取消 elseIf 标记
                    astNode.conditionBitMap.elseIf = false;
                    // 语法警告
                    const message = `${astNode.tag} 请注意！不要在同一个节点上出现 v-if， v-else-if， v-else.`;
                    warn(message);
                }
                // 处理 v-else-if 语法指令
                else {
                    // 获取 前一个 带有 v-if 或者 v-else-if 标记的节点
                    const result = findPreElement(astNode);
                    // 不允许没有前置 v-if ，却使用了 v-else-if， v-else
                    // 没有对应的 v-if 节点，将当前 ASTNode 节点弹出，不进行处理
                    if (result.prev === emptyNode) {
                        // 将该节点的引用，从树中删除
                        astNode.needDelete = true;
                            // const list = astNode.parent.children;
                            // list.splice(result.index, 1);
                        // 警告当前 v-else-if 节点无对应的 v-if 节点
                        const message = `${astNode.tag} 无对应的 v-if 前置节点`;
                        warn(message);
                    }
                    // 找到对应的 v-if 节点
                    else {
                        // 取消 v-else-if 语法指令标记， 改为 v-if 语法指令标记
                        astNode.conditionBitMap.if = true;
                        astNode.conditionBitMap.elseIf = false;
                        // 获取对应 v-if / v-else-if 节点的 IfMessage
                        const prevEle = result.prev;
                        astNode.conditionMessage.if = prevEle.conditionMessage.if;
                        // 向其中添加当前节点的 condition
                        const expression = astNode.conditionStrValueMap.elseIf;
                        astNode.conditionMessage.if.push({
                            exp: expression,
                            block: astNode
                        });
                    }
                }
            }
            // 处理 else 语句
            if (astNode.conditionBitMap.else) {
                // 不允许在同一个节点使用 v-if， v-else-if， v-else 语法指令
                if (astNode.conditionMessage.if) {
                    // 取消 else 标记
                    astNode.conditionBitMap.else = false;
                    // 语法警告
                    const message = `${astNode.tag} 请注意！不要在同一个节点上出现 v-if， v-else-if， v-else.`;
                    warn(message);
                }
                // 处理 v-else 语法指令
                else {
                    // 获取 前一个 带有 v-if 或者 v-else-if 标记的节点
                    const result = findPreElement(astNode);
                    // 不允许没有前置 v-if ，却使用了 v-else-if， v-else
                    // 没有对应的 v-if 节点，将当前 ASTNode 节点弹出，不进行处理
                    if (result.prev === emptyNode) {
                        // 将该节点的引用，从树中删除
                            astNode.needDelete = true;
                            // const list = astNode.parent.children;
                            // list.splice(result.index, 1);
                        // 警告当前 v-else 节点无对应的 v-if 节点
                        const message = `${astNode.tag} 无对应的 v-if 前置节点`;
                        warn(message);
                    }
                    // 找到对应的 v-if 节点
                    else {
                        // 取消 v-else 语法指令标记， 改为 v-if 语法指令标记
                        astNode.conditionBitMap.if = true;
                        astNode.conditionBitMap.else = false;
                        // 获取对应 v-if / v-else-if 节点的 IfMessage
                        const prevEle = result.prev;
                        astNode.conditionMessage.if = prevEle.conditionMessage.if;
                        // 向其中添加当前节点的 condition
                        astNode.conditionMessage.if.push({
                            exp: "true",
                            block: astNode
                        });
                    }
                }
            }
        }
    }

}

/**
 * 分析 AST 节点上的 v-show 指令
 * @param {ASTNode} astNode
 */
export function processShow (astNode) {

    // 节点仍需要语法指令处理
    if (!astNode.elementProcessed) {
        // 如果该节点被 v-show 语法指令标记
        if (astNode.conditionBitMap.show) {
            // 不允许在 v-pre 作用域下，使用 v-show 语法指令
            if (ASTParser.inPre) {
                // 取消 v-show 指令标记
                astNode.conditionBitMap.show = false;
                // 提示用户信息
                const message = `请不要在 v-pre 作用域下，使用 v-show 指令`;
                warn(message);
            }
            // 不允许在一个标签中使用了 v-if, v-else-if, v-else, v-show
            else if (astNode.conditionBitMap.if) {
                // 取消 v-show 指令标记
                astNode.conditionBitMap.show = false;
                // 提示用户信息
                const message = `请不要在同一个标签中使用了 v-if, v-else-if, v-else, v-show 指令 `;
                warn(message);
            }
            // 处理 v-show 语法指令信息
            if (astNode.conditionBitMap.show) {
                // 获取 show 判断表达式
                const expression = astNode.conditionStrValueMap.show;
                // 记录 show 指令信息
                astNode.conditionMessage.show = {
                    exp: expression,
                    block: astNode
                };
            }
        }

    }

}

/**
 * 分析 AST 节点上的 v-once 指令
 * @param {ASTNode} astNode
 */
export function processOnce (astNode) {

    // 节点仍需要语法指令处理
    if (!astNode.elementProcessed) {
        // 如果该节点被 v-once 语法指令标记
        if (astNode.conditionBitMap.once) {
            // 不允许在 v-pre 的作用域下，使用 v-once 指令语法
            if (ASTParser.inPre) {
                // 取消该节点的 v-show 指令
                astNode.conditionBitMap.show = false;
                // 提示用户信息
                const message = `请不要在 v-pre 的作用域下，使用 v-once 指令语法`;
                warn(message);
            }
            // 不允许在 v-once 的作用域下 重复声明 v-once
            else if (ASTParser.inOnce) {
                // 取消该节点的 v-once 指令
                astNode.conditionBitMap.once = false;
                // 提示用户信息
                const message = `请不要在 v-once 的作用域下重复使用 v-once 指令语法`;
                warn(message);
            }
            // 不允许在 v-for 标记的 template 节点上 出现 v-once 语法标记
            else if (astNode.tag === "template" && astNode.conditionBitMap.for) {
                // 取消该节点的 v-once 指令
                astNode.conditionBitMap.once = false;
                // 提示用户信息
                const message = `请不要在 v-for 标记的 template 节点上使用 v-once 语法`;
                warn(message);
            }
            // 正常处理流程
            if (astNode.conditionBitMap.once) {
                // once 全局标志 入栈
                ASTParser.onceStateStack.push(ASTParser.inOnce);
                // ASTParser.inOnce 全局标志 置位
                ASTParser.inOnce = true;
                // 设置 conditionMessage
                astNode.conditionMessage.once = { once: true };
            }
        }
    }

}

/**
 * 解析不使用子组件作用域的插槽
 * 分析 AST 节点上的 v-slot 指令
 * @param {ASTNode} astNode
 */
export function processSlotDirective (astNode) {
    // 如果节点仍需要被处理
    if (!astNode.elementProcessed) {
        // 该节点被 v-slot 语法指令标记
        if (astNode.conditionBitMap.slotImplement) {
            // 不允许在 v-pre 作用域下，使用 v-slot 指令
            if (ASTParser.inPre) {
                // 取消 v-for 指令标记
                astNode.conditionBitMap.slotImplement = false;
                // 提示用户信息
                const message = `请不要在 v-pre 作用域下，使用 v-slot 指令`;
                warn(message);
            }
            // 检查是否存在父节点是否是组件节点
            const isParentComponent = (
                astNode.parent
                && !isReservedTag(astNode.parent.tag)
                && astNode.parent.tag !== 'slot'
            );
            // 不允许在父节点不是组件节点的情况下，在该节点使用 v-slot 指令
            if (!isParentComponent) {
                // 取消 v-slot 指令标记
                astNode.conditionBitMap.slotImplement = false;
                // 删除该节点
                astNode.needDelete = true;
                // 用户提示信息
                const message = `请不要在 ${astNode.tag} 父节点不是组件节点的情况下在该节点使用 v-slot 指令`;
                warn(message);
            }
            // 不允许在 slot 节点上使用 v-slot 指令
            if (
                astNode.conditionBitMap.slotImplement
                && astNode.tag === "slot"
            ) {
                // 取消 v-slot 指令标记
                astNode.conditionBitMap.slotImplement = false;
                // 删除该节点
                astNode.needDelete = true;
                // 用户提示信息
                const message = `请不要在 slot 节点上使用 v-slot 指令`;
                warn(message);
            }

            // 如果依然存在 v-slot 语法标记, 进行 v-slot 指令的处理
            if (astNode.conditionBitMap.slotImplement) {
                // 处理 slot 指令信息
                const conditionStrValue = astNode.conditionStrValueMap.slotImplement;
                // 非具名插槽，没有语法指令，所以在 conditionStrValue 中的信息是 null
                // 这里需要在 AST 解析时，为其添加默认插槽信息
                const name = isDef(conditionStrValue) ? conditionStrValue.name : 'default';
                const scope = isDef(conditionStrValue) ? conditionStrValue.scope : undefined;
                astNode.conditionMessage.slotImplement = {
                    name: name,
                    scope: scope,
                };
                // // 向父组件节点添加 slot 节点信息
                // const parentNode = astNode.parent;
                // const slotImplementMap = parentNode.conditionMessage.slotImplementMap;
                // name !== 'default'
                //     ? slotImplementMap[name] = astNode
                //     : slotImplementMap.default.push(astNode);
            }
        }
    }
}

/**
 * 判断 astNode 节点是不是一个组件,并在 astNode 上进行标记
 * @param {ASTNode} astNode
 */
export function processComponent (astNode) {
    // 判断是否为 组件节点
    const tag = astNode.tag;
    const isComponent = !isReservedTag(tag) && tag !== 'slot';

    // 在 v-pre 作用域内，禁止使用 component 组件语法
    if (ASTParser.inPre) {
        if (isComponent) {
            // 取消 component 语法标记
            astNode.conditionBitMap.component = false;
            // 标记静态节点
            astNode.isDynamic = false;
            // 节点处理完毕
            astNode.elementProcessed = true;
            // 用户提示信息
            const message = `请不要在 v-pre 的作用域内使用组件.`;
            warn(message);
        }
    }

    // 如果该节点未处理完毕且是组件
    if (!astNode.elementProcessed && isComponent) {
        // 设置 component 标志
        astNode.conditionBitMap.component = true;
        // 标志节点为动态节点
        astNode.isDynamic = true;
        // 判断 component 是否有孩子节点，如果有全部作为插槽节点
        astNode.conditionMessage.component = {
            componentName: tag,
            slotImplementMap: {
                default: []
            },
        };
    }
}

/**
 * 分析 slot 标签
 * @param {ASTNode} astNode
 */
export function processSlot (astNode) {

    // 如果该节点未处理结束
    if (!astNode.elementProcessed) {
        // 如果被 slot 语法标记
        astNode.conditionBitMap.slotDeclaration = true;
        // 检验是否需要处理
        // 在非组件模板下使用, 不进行处理
        if (!ASTParser.isComponentTemplate || ASTParser.inPre) {
            astNode.conditionBitMap.slotDeclaration = false;
        }
        // 非法的语法情况
        if (!astNode.conditionBitMap.slotDeclaration) {
            // 标记节点指令处理结束
            astNode.elementProcessed = true;
            // 删除 slot 插槽声明节点，不渲染该节点
            astNode.needDelete = true;
            // 提示用户信息
            if (!ASTParser.isComponentTemplate) {
                const message = `请不要在非组件模板的情况下，使用 v-interface 去声明 slot`;
                warn(message);
            }
            else {
                const message = `请不要在 v-pre 作用域下使用 slot 与其他动态指令功能`;
                warn(message);
            }
        }
        // 合法的语法情况
        if (astNode.conditionBitMap.slotDeclaration) {
            // 解析 slot 语法值
            const name = astNode.staticAttrMap['name'] || 'default';
            astNode.conditionMessage.slotDeclaration = {
                name: name,
            };
        }
    }

}

/**
 * 处理当前节点的 动态指令
 * @param {ASTNode} astNode
 */
export function processElement (astNode) {
    // 解析语法信息， 这里的顺序从高优先级到低优先级
    // 这样当高优先级语法，与低优先级语法冲突时，高优先级会被先处理
    processPre(astNode);
    processFor(astNode);
    processKey(astNode);
    processIf(astNode);
    processShow(astNode);
    processOnce(astNode);
    processSlotDirective(astNode);
    // 检查该节点是否是组件或者是插槽
    if (astNode.tag === "slot") {
        processSlot(astNode);
    }
    else {
        processComponent(astNode);
    }

    // 解析完毕
    astNode.elementProcessed = true;
}

/**
 * 处理注释节点
 * @param {ASTNode} astNode
 */
export function processComment (astNode) {
    // 节点处理完毕
    astNode.elementProcessed = true;
    // 非动态节点
    astNode.isDynamic = false;
}

// 插值表达式处理
const DYNAMIC_TEXT_REGEX = /\{\{[^{}]*\}\}/;

/**
 * 处理文字节点，解析可能存在的插值表达式
 * @param {ASTNode} astNode
 */
export function processText (astNode) {
    // 检查是否含有插值表达式
    const hasDynamicText = DYNAMIC_TEXT_REGEX.test(astNode.textContent);

    // 如果在 v-pre 的作用域范围内
    if (ASTParser.inPre && hasDynamicText) {
        // 节点处理完毕
        astNode.elementProcessed = true;
        // 非动态节点
        astNode.isDynamic = false;
        // 提示用户信息
        const message = `请不要在 v-pre 下使用 {{}} 插值表达式.`;
        warn(message)
    }

    // 如果该节点未处理完毕
    if (!astNode.elementProcessed) {
        // 获取字符串的值
        let text = astNode.textContent;

        // 插值表达式 匹配结果
        let matchResult = text.match(DYNAMIC_TEXT_REGEX);
        const tokens = new Array();
        // 匹配 插值表达式
        while (matchResult !== null) {
            // 表达式前的字符串
            const start = matchResult.index;
            const preText = text.substring(0, start);
            if (preText.length !== 0) {
                tokens.push({ text: preText, isDynamic: false });
            }

            const matchStr = matchResult[0].trim();
            const exp = matchStr.substring(2, matchStr.length-2).trim();
            if (exp.length !== 0) {
                tokens.push({ text: exp, isDynamic: true });
            }

            // 切割 text 字符串
            const finish = matchResult.index + matchStr.length;
            text = text.substring(finish);

            // 匹配下一个插值表达式
            matchResult = text.match(DYNAMIC_TEXT_REGEX);
        }
        if (text.length !== 0) {
            tokens.push({ text: text, isDynamic: false });
        }

        // ================ 创建 多个 Text ASTNode 节点

        // 获取 父节点
        const parent = astNode.parent;

        let start = astNode.start;
        const tokensNodeArray = new Array();
        for (let i=0; i<tokens.length; i++) {
            const astNode = new ASTNode(
                "text",
                HTML_NODE_TYPE.TEXT,
                HTML_TAG_STATUS.SINGLE,
                [],
                start,
                parent,
                [],
                tokens[i].text
            );

            // 标记节点处理完毕
            astNode.elementProcessed = true;
            // 标记节点是否为动态节点
            astNode.isDynamic = tokens[i].isDynamic;

            // 装入 token 数组
            tokensNodeArray.push(astNode);
            start += tokens[i].text.length;
        }

        // 对原 文本节点 进行替换
        const childList = astNode.parent.children;
        const index = indexOf(astNode, childList);
        childList.splice(index, 1, ...tokensNodeArray);
    }
}

/**
 * 本节点已被处理完毕，将部分全局标志回复
 * @param {ASTNode} astNode
 */
export function resetGlobalDirectiveBit (astNode) {
    if (astNode.conditionBitMap.pre) {
        ASTParser.inPre = ASTParser.preStateStack.pop();
    }
    else {
        if (astNode.conditionBitMap.slot) {
            ASTParser.inSlot = ASTParser.slotStateStack.pop();
        }
        if (astNode.conditionBitMap.once) {
            ASTParser.inOnce = ASTParser.onceStateStack.pop();
        }
        if (astNode.conditionBitMap.for) {
            ASTParser.inFor = ASTParser.forStateStack.pop();
        }
    }
}

/**
 * 寻找前一个带有 v-if 或 v-else-if 的节点， 则返回 {prev: prevEle, index: index}
 * 如果传入一个不存在的节点，则返回 {prev: emptyNode, index: index}
 * @param {ASTNode} astNode
 * @return {{ prev: ASTNode, index: Number }}
 */
function findPreElement (astNode) {
    const nodeList = astNode.parent.children;
    const index = indexOf(astNode, nodeList);
    // 如果 index 为 -1 说明没有该节点，无法寻找，返回null
    if (index === -1) {
        return null;
    }
    // 获取前置节点
    const prevEle = nodeList[index-1];
    // 非法语法情况警告
    if (prevEle.type === HTML_NODE_TYPE.TEXT) {
        const message = `${astNode.tag} 的前置节点是 Text 节点, 如果未找到对应的 v-if 节点，那么 ${astNode.tag} 将不被渲染`;
        warn(message);
        // 返回空节点 emptyNode
        return {prev: emptyNode, index: index};
    }
    // 返回前置节点
    return {prev: prevEle, index: index};
}

/**
 * 找出该ASTNode节点在队列中的索引
 * @param {ASTNode} target
 * @param {Array<ASTNode>} list
 * @return {Number}
 */
function indexOf (target, list) {
    for (let i=0; i<list.length; i++) {
        const node = list[i];
        if (target === node) {
            return i;
        }
    }
    return -1;
}

